using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DicCtrl<T, F,KEY> : IDataModelCenter<T, F, KEY>
    where T : class, IDataModel<T, F,KEY>, new() where F : class
{
    SimpleObjectPool<T> pool = new SimpleObjectPool<T>(() => new());
    Dictionary<KEY,T> datas;
    List<T> arrayed_datas;
    int eventId;
    T empty_value;

    public DicCtrl(System.Func<T> creator,int eventId, int capacity = 32, int poolcapacity = 32)
    {
        this.eventId = eventId;
        pool = new SimpleObjectPool<T>(creator, poolcapacity);
        datas = new Dictionary<KEY,T>(capacity * 2);
        arrayed_datas = new(capacity);
        empty_value = creator();
    }

    public void Clear()
    {
        arrayed_datas.Clear();
        foreach (var d in datas.Values)
        {
            d.Reset();
            pool.Put(d);
        }
        datas.Clear();
    }

    public void Initialze(IEnumerable<F> collections)
    {
        Clear();
        var it = collections.GetEnumerator();
        while (it.MoveNext())
        {
            var data = pool.Get();
            data.Set(it.Current);
            datas.Add(data.Key,data);
            arrayed_datas.Add(data);
        }
        arrayed_datas.Sort((x,y)=>
        {
            return x.LessThan(y) ? -1 : y.LessThan(x) ? 1 : 0;
        });
        EventDispatchManager.Instance.SendEvent(CtrlEventID.EVENT_DATA_FACTORY_DATA_CHANGED, eventId, Count);
    }

    public bool Contains(F p)
    {
        return datas.ContainsKey(empty_value.KeyOf(p));
    }

    public void Modify(F p)
    {
        if(Contains(p))
        {
            datas[empty_value.KeyOf(p)].Set(p);
            EventDispatchManager.Instance.SendEvent(CtrlEventID.EVENT_DATA_FACTORY_DATA_CHANGED, eventId, Count);
        }
    }

    public void Add(F p)
    {
        if (Contains(p))
        {
            Modify(p);
            return;
        }

        var data = pool.Get();
        data.Set(p);
        datas.Add(data.Key, data);
        arrayed_datas.Add(data);
        arrayed_datas.Sort((x, y) =>
        {
            return x.LessThan(y) ? -1 : y.LessThan(x) ? 1 : 0;
        });
        EventDispatchManager.Instance.SendEvent(CtrlEventID.EVENT_DATA_FACTORY_DATA_CHANGED, eventId, Count);
    }

    public bool Remove(KEY key)
    {
        if (datas.ContainsKey(key))
        {
            arrayed_datas.Remove(datas[key]);
            datas.Remove(key);
            EventDispatchManager.Instance.SendEvent(CtrlEventID.EVENT_DATA_FACTORY_DATA_CHANGED, eventId, Count);
            return true;
        }
        return false;
    }

    public T Get(int index)
    {
        if(index >= 0 && index < arrayed_datas.Count)
        {
            return arrayed_datas[index];
        }
        return default(T);
    }

    public int Count => datas.Count;
}
